#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  

#define MAX_RECORDS 100  
#define MAX_CATEGORY_LENGTH 30  
#define MAX_NOTE_LENGTH 100  

typedef struct 
{  
    char date[11]; 
    double amount;  
    char category[MAX_CATEGORY_LENGTH];  
    char note[MAX_NOTE_LENGTH];  
} Record;  

typedef struct 
{  
    Record records[MAX_RECORDS];  
    int count;  
    double monthly_budget;  
} BillManager;  

void add_income(BillManager *manager);  
void add_expense(BillManager *manager);  
void display_records(BillManager *manager);  
void query_records(BillManager *manager);  
void set_budget(BillManager *manager);  
void monthly_statistics(BillManager *manager);  
void print_menu();  
void clear_buffer();  

int main() 
{  
    BillManager manager = { .count = 0, .monthly_budget = 0.0 };  
    int choice;  

    do {  
        print_menu();  
        printf("请选择操作: ");  
        scanf("%d", &choice);  
        clear_buffer(); // 清理输入缓冲区  

        switch (choice) {  
            case 1: 
            add_income(&manager); 
            break;  
            case 2: 
            add_expense(&manager); 
            break;  
            case 3: 
            display_records(&manager); 
            break;  
            case 4: 
            query_records(&manager); 
            break;  
            case 5: 
            set_budget(&manager); 
            break;  
            case 6: 
            monthly_statistics(&manager); 
            break;  
            case 7: 
            printf("退出系统。\n");
            break;
            default:
            printf("无效选项，请重试。\n");
        }  
    } while (choice != 7);  

    return 0;  
}  

void print_menu() 
{  
    printf("\n=== 个人账单管理系统 ===\n");  
    printf("1. 记录收入\n");  
    printf("2. 记录支出\n");  
    printf("3. 展示账单\n");  
    printf("4. 查询账单\n");  
    printf("5. 设置预算\n");  
    printf("6. 月度统计\n");  
    printf("7. 退出系统\n");  
}  

void clear_buffer() 
{  
    while (getchar() != '\n');  
}  

void add_income(BillManager *manager) 
{  
    if (manager->count >= MAX_RECORDS) 
    {  
        printf("记录已满，无法添加新收入。\n");  
        return;  
    }  

    Record *record = &manager->records[manager->count];  
    printf("请输入收入日期 (YYYY-MM-DD): ");  
    fgets(record->date, sizeof(record->date), stdin);  
    record->date[strcspn(record->date, "\n")] = 0; // 去除换行符  

    printf("请输入收入金额: ");  
    scanf("%lf", &record->amount);  
    clear_buffer(); // 清理输入缓冲区  

    if (record->amount <= 0) {  
        printf("收入金额必须为正数！\n");  
        return;  
    }  

    printf("请输入收入类别: ");  
    fgets(record->category, sizeof(record->category), stdin);  
    record->category[strcspn(record->category, "\n")] = 0; 

    printf("请输入备注: ");  
    fgets(record->note, sizeof(record->note), stdin);  
    record->note[strcspn(record->note, "\n")] = 0;

    manager->count++;  
    printf("收入记录添加成功！\n");  
}  

void add_expense(BillManager *manager) 
{  
    if (manager->count >= MAX_RECORDS) 
    {  
        printf("记录已满，无法添加新支出。\n");  
        return;  
    }  

    Record *record = &manager->records[manager->count];  
    printf("请输入支出日期 (YYYY-MM-DD): ");  
    fgets(record->date, sizeof(record->date), stdin);  
    record->date[strcspn(record->date, "\n")] = 0;
    printf("请输入支出金额: ");  
    scanf("%lf", &record->amount);  
    clear_buffer(); // 清理输入缓冲区  

    if (record->amount <= 0) {  
        printf("支出金额必须为正数！\n");  
        return;  
    }  

    printf("请输入支出类别: ");  
    fgets(record->category, sizeof(record->category), stdin);  
    record->category[strcspn(record->category, "\n")] = 0;

    printf("请输入备注: ");  
    fgets(record->note, sizeof(record->note), stdin);  
    record->note[strcspn(record->note, "\n")] = 0;  

    manager->count++;  
    printf("支出记录添加成功！\n");  
}  

void display_records(BillManager *manager) {  
    printf("\n=== 账单记录 ===\n");  
    double total_income = 0.0, total_expense = 0.0;  

    for (int i = 0; i < manager->count; i++) {  
        Record *record = &manager->records[i];  
        if (record->amount > 0) { // 收入  
            printf("收入 - 日期: %s, 金额: %.2f, 类别: %s, 备注: %s\n",  
                   record->date, record->amount, record->category, record->note);  
            total_income += record->amount;  
        } else { // 支出  
            printf("支出 - 日期: %s, 金额: %.2f, 类别: %s, 备注: %s\n",  
                   record->date, -record->amount, record->category, record->note);  
            total_expense += -record->amount;  
        }  
    }  

    printf("\n总收入: %.2f, 总支出: %.2f\n", total_income, total_expense);  
}  

void query_records(BillManager *manager) {  
    char category[MAX_CATEGORY_LENGTH];  
    char date[11];  
    printf("请输入查询类别 (留空则不限制): ");  
    fgets(category, sizeof(category), stdin);  
    category[strcspn(category, "\n")] = 0;

    printf("请输入查询日期 (留空则不限制): ");  
    fgets(date, sizeof(date), stdin);  
    date[strcspn(date, "\n")] = 0;

    printf("\n=== 查询结果 ===\n");  
    for (int i = 0; i < manager->count; i++) {  
        Record *record = &manager->records[i];  
        int match_category = (strcmp(category, "") == 0 || strcmp(record->category, category) == 0);  
        int match_date = (strcmp(date, "") == 0 || strcmp(record->date, date) == 0);  

        if (match_category && match_date) {  
            if (record->amount > 0) { // 收入  
                printf("收入 - 日期: %s, 金额: %.2f, 类别: %s, 备注: %s\n",  
                       record->date, record->amount, record->category, record->note);  
            } else { // 支出  
                printf("支出 - 日期: %s, 金额: %.2f, 类别: %s, 备注: %s\n",  
                       record->date, -record->amount, record->category, record->note);  
            }  
        }  
    }  
}  

void set_budget(BillManager *manager) {  
    printf("请输入每月支出预算限额: ");  
    scanf("%lf", &manager->monthly_budget);  
    clear_buffer(); // 清理输入缓冲区  

    if (manager->monthly_budget < 0) {  
        printf("预算不能为负数！\n");  
        return;  
    }  

    printf("预算设置成功！当前预算: %.2f\n", manager->monthly_budget);  
}  

void monthly_statistics(BillManager *manager) 
{  
    double total_income = 0.0,total_expense = 0.0;  
    double category_expenses[MAX_CATEGORY_LENGTH] = {0};
    char categories[MAX_RECORDS][MAX_CATEGORY_LENGTH];
    int category_count = 0;

    for (int i = 0; i < manager->count; i++) 
    {  
        Record *record = &manager->records[i];  
        if (record->amount > 0) 
        {  
            total_income += record->amount;  
        } else 
        {  
            total_expense += -record->amount;  
            int found = 0;  
            for (int j = 0; j < category_count; j++) 
            {  
                if (strcmp(categories[j], record->category) == 0) 
                {  
                    category_expenses[j] += -record->amount;  
                    found = 1;  
                    break;  
                }  
            }  
            if (!found) 
            {  
                strcpy(categories[category_count], record->category);  
                category_expenses[category_count] = -record->amount;  
                category_count++;  
            }
        }
    }

    printf("\n=== 月度统计 ===\n");  
    printf("总收入: %.2f\n", total_income);  
    printf("总支出: %.2f\n", total_expense);  
    printf("剩余预算: %.2f\n", manager->monthly_budget - total_expense);  
    printf("\n各类支出:\n");  
    for (int i = 0; i < category_count; i++) {  
        printf("%s: %.2f\n", categories[i], category_expenses[i]);  
    }  
}